package com.dudu.timer;

import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Properties;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

import com.dudu.bean.ReportDailyBean;
import com.dudu.dao.DailyReportDao;
import com.dudu.service.IOperationPlatformService;
import com.dudu.service.impl.OperationPlatformServiceImpl;
import com.dudu.utils.DateUtils;
import com.dudu.utils.DictionaryUtils;

import core.CoreDao;
import core.CoreDaoInvoke;
import core.util.EmailSend;

/**
 * 短信日报表
 * 
 * @author jack
 * @time 2017-06-14
 */
public class SmsDailyReportJob implements Job {
    // log日志
    public static final Logger log = core.util.Logger.getLogger(SmsDailyReportJob.class.getName());
    // 数据库连接
    private CoreDao coreDao = CoreDaoInvoke.getInstance();
    // 日报表dao
    private DailyReportDao dailyReportDao = new DailyReportDao();
    private IOperationPlatformService operationPlatformServiceImpl = new OperationPlatformServiceImpl();

    @Override
    public void execute(JobExecutionContext arg0) throws JobExecutionException {
	log.info("执行短信日报表job");
	try {
	    String emailAdressStr = DictionaryUtils.getValueByTypeAndKey("report_email", "smsEmail"); // 获得日报表接收邮箱
	    if (StringUtils.isNotBlank(emailAdressStr)) {
		StringBuffer content = new StringBuffer(); // 邮件内容
		String yestoday = DateUtils.getYestodayByFormat(); // 日期格式yyyy-MM-dd
		String beginTime = DateUtils.getTimeAddBeginStr(yestoday); // 格式"2016-08-02 00:00:00"
		String endTime = DateUtils.getTimeAddEndStr(yestoday); // 格式"2016-08-02 23:59:59"
		JSONArray appArray = queryAppList(); // 查询所有的APP
		// 应用消耗日统计报表
		this.reportDailyByApp(content, beginTime, endTime, appArray);

		List<JSONObject> custArray = this.queryCustList(beginTime, endTime); // 查询活跃客户
		// 计费账号消耗日统计报表
		this.reportDailyByCust(content, beginTime, endTime, custArray);

		String[] emailAdressArray = emailAdressStr.split(",");
		for (String emailAdress : emailAdressArray) {
		    Thread.sleep(1000 * 10); // 邮件服务器不支持连续发送
		    EmailSend.sendMail(emailAdress, "短信日报表" + yestoday, content.toString(), null, null); // 发送邮件
		}

	    } else {
		log.error("未配置短信日报表接收邮件地址");
	    }
	} catch (Exception ex) {
	    ex.getMessage();
	    log.error("短信日报表error");
	}
    }

    /**
     * 查询APP列表
     * 
     * @param 1：一页
     * @param 200: 200行数据
     * @return
     */
    private JSONArray queryAppList() {
	return operationPlatformServiceImpl.queryAppItems("", "", "", 1, 200).optJSONArray("data");
    }

    /**
     * 查询日活跃计费账号Top50
     * 
     * @param beginTime
     * @param endTime
     * @return
     */
    private List<JSONObject> queryCustList(String beginTime, String endTime) {
	return this.dailyReportDao.queryCustaccountSMS(coreDao, beginTime, endTime, 50);
    }

    /**
     * 应用短信消耗日统计报表
     * 
     * @param content
     * @param beginTime
     * @param endTime
     * @param appArray
     */
    private void reportDailyByApp(StringBuffer content, String beginTime, String endTime, JSONArray appArray) {
	if (StringUtils.isNotBlank(beginTime) && StringUtils.isNotBlank(endTime) && appArray != null) {
	    BigDecimal _100 = new BigDecimal(100);

	    List<ReportDailyBean> reportDailyBeanList = new ArrayList<ReportDailyBean>();
	    for (int i = 0; i < appArray.size(); i++) {
		JSONObject appJson = appArray.getJSONObject(i);
		String isvName = appJson.optString("isv_name");
		String appName = appJson.optString("app_name");
		String appKey = appJson.optString("app_key");

		List<JSONObject> dataList = this.dailyReportDao.queryByAppAndTimeSMS(coreDao, appKey, beginTime, endTime);
		if (dataList != null) {
		    for (int j = 0; j < dataList.size(); j++) {
			JSONObject data = dataList.get(j);
			String productCode = data.optString("product_code");
			String totalCount = data.optString("total_count"); // 总数量
			String successCount = data.optString("success_count"); // 下发成功数
			String failCount = data.optString("fail_count"); // 下发失败数
			String consumeCount = data.optString("consume_count"); // 消耗量
			String noStatusCount = "0"; // 未知量：没有返回下发结果
			String successPercent = "0%"; // 成功率
			if (!"0".equals(totalCount)) {
			    noStatusCount = String.valueOf(Integer.valueOf(totalCount) - Integer.valueOf(successCount) - Integer.valueOf(failCount));
			    BigDecimal fenzi = new BigDecimal(successCount).multiply(_100);
			    BigDecimal fenmu = new BigDecimal(totalCount);
			    successPercent = fenzi.divide(fenmu, 2, BigDecimal.ROUND_HALF_UP) + "%";
			}

			ReportDailyBean reportDailyBean = new ReportDailyBean();
			reportDailyBean.setIsvName(isvName);
			reportDailyBean.setAppName(appName);
			reportDailyBean.setProductName(this.converProductCodeToName(productCode));
			reportDailyBean.setTotalCount(totalCount);
			reportDailyBean.setSuccessCount(successCount);
			reportDailyBean.setFailCount(failCount);
			reportDailyBean.setNoStatusCount(noStatusCount);
			reportDailyBean.setSuccessPercent(successPercent);
			reportDailyBean.setTotalTime(consumeCount); // 消耗量
			reportDailyBeanList.add(reportDailyBean);
		    }
		}
	    }

	    Collections.sort(reportDailyBeanList);

	    try {
		String reportDailyContent = getTempleteContent("vm/reportSmsDailyApp.vm", reportDailyBeanList);
		content.append(reportDailyContent);
	    } catch (Exception e) {
		log.error("应用短信消耗日统计报表渲染模板error");
	    }
	}
    }

    /**
     * 计费账号短信消耗日统计报表
     * 
     * @param content
     * @param beginTime
     * @param endTime
     * @param custArray
     * @throws UnsupportedEncodingException
     */
    private void reportDailyByCust(StringBuffer content, String beginTime, String endTime, List<JSONObject> custArray) throws UnsupportedEncodingException {
	if (StringUtils.isNotBlank(beginTime) && StringUtils.isNotBlank(endTime) && custArray != null) {
	    BigDecimal _100 = new BigDecimal(100);

	    List<ReportDailyBean> reportDailyBeanList = new ArrayList<ReportDailyBean>();
	    for (int i = 0; i < custArray.size(); i++) {
		JSONObject custJson = custArray.get(i);
		String custAccount = custJson.optString("cust_account");
		String appKey = custJson.optString("app_key");
		String custName = URLDecoder.decode(operationPlatformServiceImpl.queryCustomerInfo(custAccount).optString("cust_name"), "UTF-8");
		JSONObject appJson = operationPlatformServiceImpl.queryAppItems("", "", appKey, 1, 1).optJSONArray("data").getJSONObject(0);
		String isvName = appJson.optString("isv_name");
		String appName = appJson.optString("app_name");

		List<JSONObject> dataList = this.dailyReportDao.queryByCustaccountAndTimeSMS(coreDao, custAccount, beginTime, endTime);
		if (dataList != null) {
		    for (int j = 0; j < dataList.size(); j++) {
			JSONObject data = dataList.get(j);
			String productCode = data.optString("product_code");
			String totalCount = data.optString("total_count"); // 总数量
			String successCount = data.optString("success_count"); // 下发成功数
			String failCount = data.optString("fail_count"); // 下发失败数
			String consumeCount = data.optString("consume_count"); // 消耗量
			String noStatusCount = "0"; // 未知量：没有返回下发结果
			String successPercent = "0%"; // 成功率
			if (!"0".equals(totalCount)) {
			    noStatusCount = String.valueOf(Integer.valueOf(totalCount) - Integer.valueOf(successCount) - Integer.valueOf(failCount));
			    BigDecimal fenzi = new BigDecimal(successCount).multiply(_100);
			    BigDecimal fenmu = new BigDecimal(totalCount);
			    successPercent = fenzi.divide(fenmu, 2, BigDecimal.ROUND_HALF_UP) + "%";
			}

			ReportDailyBean reportDailyBean = new ReportDailyBean();
			reportDailyBean.setIsvName(isvName);
			reportDailyBean.setAppName(appName);
			reportDailyBean.setProductName(this.converProductCodeToName(productCode));
			reportDailyBean.setCustAccount(custAccount);
			reportDailyBean.setCustName(custName);
			reportDailyBean.setTotalCount(totalCount);
			reportDailyBean.setSuccessCount(successCount);
			reportDailyBean.setFailCount(failCount);
			reportDailyBean.setNoStatusCount(noStatusCount);
			reportDailyBean.setSuccessPercent(successPercent);
			reportDailyBean.setTotalTime(consumeCount); // 消耗量
			reportDailyBeanList.add(reportDailyBean);
		    }
		}
	    }

	    Collections.sort(reportDailyBeanList,new Comparator<ReportDailyBean>(){
		@Override
		public int compare(ReportDailyBean o1, ReportDailyBean o2) {
		    Integer count1 = Integer.parseInt(o1.getTotalCount());
		    Integer count2 = Integer.parseInt(o2.getTotalCount());
		    return count2.compareTo(count1);
		}
	    });
	    
	    try {
		String reportDailyContent = getTempleteContent("vm/reportSmsDailyCust.vm", reportDailyBeanList);
		content.append(reportDailyContent);
	    } catch (Exception e) {
		log.error("计费账号短信消耗日统计报表渲染模板error");
	    }
	}
    }

    /**
     * 产品编码和名称的转换
     * 
     * @param productCode
     * @return
     */
    private String converProductCodeToName(String productCode) {
	String productName = "";
	if ("SMMS".equals(productCode)) {
	    productName = "通知类短信";
	} else if ("ADSMMS".equals(productCode)) {
	    productName = "营销类短信";
	} else {
	    productName = productCode;
	}
	return productName;
    }

    /**
     * 解析模板
     * 
     * @param templete
     * @param list
     * @return
     * @throws Exception
     */
    @SuppressWarnings({ "deprecation", "rawtypes" })
    public static String getTempleteContent(String templete, List list) throws Exception {
	StringWriter writer = null;
	try {
	    URL url = Thread.currentThread().getContextClassLoader().getResource("");
	    String realPath = url.getPath();
	    VelocityEngine ve = new VelocityEngine();
	    Properties p = new Properties();
	    p.put(Velocity.FILE_RESOURCE_LOADER_PATH, URLDecoder.decode(realPath));
	    ve.init(p);
	    Template t = ve.getTemplate(templete, "UTF-8");
	    VelocityContext context = new VelocityContext();
	    context.put("array", list);
	    writer = new StringWriter();
	    t.merge(context, writer);
	} catch (Exception e) {
	    log.info("<===获得模板出错==>");
	    e.printStackTrace();
	    throw e;
	}
	return writer.toString();
    }

    public static void main(String[] args) {

    }

}
